/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "module.h"

namespace xos_http
{
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static module::ITEM_DATA xos_item_data;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    module::module()
    {
        init_data();
    }

    module::~module()
    {
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int module::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int module::delete_module_file() const
    {
        int ret = 0;
        if( !m_bDeleteFileWhenClose )
        {
            return ret;
        }
        if( !m_full_file.empty() )
        {
            xos::i_dir * pDir = mgr::container()->xos()->dir();
            pDir->delete_file( m_full_file.c_str() );
            xos_stl::release_interface( pDir );
        }
        return ret;
    }

    int module::init_data()
    {
        int ret = 0;
        m_pServletModule = 0;
        m_pServletMgr = 0;
        m_pNum = 0;
        m_pFile = 0;
        m_bDeleteFileWhenClose = false;
        m_full_path = "";
        m_full_file = "";
        m_full_uri = "";
        m_uri_path = "";
        m_file = "";
        m_name = "";
        m_id = "";
        m_ext = "";
        m_mTime = 0;
        return ret;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int module::find_and_create_dir_by_uri_path()
    {
        int ret = 0;

        // /8080/www.cat.com/root/servlet
        xos::i_crt * pCrt = mgr::container()->crt();
        char uri[4096] = { 0 };
        char * psz = uri;
        port * pPort = 0;
        host * pHost = 0;
        path * pPath = 0;

        // 把/都换成0，拆分路径
        if( 0 == ret )
        {
            pCrt->strncpy( uri, sizeof( uri ) / sizeof( uri[0] ), m_uri_path.c_str(), m_uri_path.length() );
            while( *psz != 0 )
            {
                if( *psz == '/' )
                {
                    *psz = 0;
                }
                ++psz;
            }
            // 因为while( *psz++ != 0 );总是移动到0的下一个位置
            // 但是字串结束的0的下一个位置未必是0，所以提前清一下
            ++psz;
            *psz = 0;
            // 让psz指向第一个拆分出来的路径的前边
            psz = uri;
        }
        // 8080
        if( 0 == ret )
        {
            while( *psz++ != 0 );
            pPort = (port *)port::get()->obj( psz );
            if( !pPort )
            {
                ret = 1;
            }
        }
        // www.cat.com
        if( 0 == ret )
        {
            while( *psz++ != 0 );
            pHost = (host *)pPort->m_pProp->obj( psz );
            if( !pHost )
            {
                ret = 1;
            }
        }
        // path，其实就是root
        if( 0 == ret )
        {
            while( *psz++ != 0 );
            pPath = (path *)pHost->m_pProp->obj( psz );
            if( !pPath )
            {
                ret = 1;
            }
        }
        // path
        while( 0 == ret )
        {
            while( *psz++ != 0 );
            if( *psz == 0 )
            {
                break;
            }
            path * pT = (path *)pPath->get_path( psz );
            if( !pT )
            {
                pPath = pPath->add_dir_path( psz );
            }
            else
            {
                pPath = pT;
            }
        }
        // add
        if( 0 == ret )
        {
            m_pFile->m_pFatherPath = pPath;
        }

        return ret;
    }

    int module::split_file_ext()
    {
        int ret = 0;
        xos_box::i_string * pStr = mgr::container()->box()->string();
        const char * lpszExt = 0;
        lpszExt = mgr::container()->common()->misc()->ext( m_file.c_str(), pStr );
        if( lpszExt )
        {
            m_name = pStr->get( 0, 0 );
            m_ext = lpszExt;
        }
        xos_stl::release_interface( pStr );
        return ret;
    }

    int module::fmt_file_name()
    {
        int ret = 0;
        xos_box::i_string * pStr = mgr::container()->box()->string();
        xos::i_time * pTime = mgr::container()->xos()->tm();
        xos::i_crt * pCrt = mgr::container()->crt();
        pTime->set_wall_time_s( m_mTime );
        pTime->get_time_name_ymdhms( pStr );
        m_file = pStr->get( 0, 0 );
        pCrt->sprintf( pStr, "%s_%s.%s", m_name.c_str(), m_file.c_str(), config::get()->m_xos.c_str() );
        m_file = pStr->get( 0, 0 );
        xos_stl::release_interface( pTime );
        xos_stl::release_interface( pStr );
        return ret;
    }

    int module::close_servlet()
    {
        int ret = 0;
        xos_stl::release_interface( m_pServletMgr );
        xos_stl::release_interface( m_pServletModule );
        return ret;
    }

    int module::load_servlet()
    {
        int ret = 0;

        http::i_servlet_mgr * pModule = 0;
        xos::i_dynamic * pDll = 0;
        http::f_servlet fun = 0;

        if( 0 == ret )
        {
            pDll = mgr::container()->xos()->dynamic();
        }

        if( 0 == ret )
        {
            ret = pDll->load_and_get( (void **)&fun,
                m_full_file.c_str(),
                "servlet" );
        }

        if( 0 == ret )
        {
            ret = fun( mgr::container(), &pModule );
        }

        if( 0 == ret )
        {
            m_pServletMgr = pModule;
            m_pServletModule = pDll;
            pModule = 0;
            pDll = 0;
        }

        xos_stl::release_interface( pModule );
        xos_stl::release_interface( pDll );

        return ret;
    }

    int module::proc_file()
    {
        int ret = 0;

        if( 0 == ret )
        {
            split_file_ext();
            if( m_ext != config::get()->m_xos )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            ret = load_servlet();
        }

        return ret;
    }

    int module::release_ref()
    {
        int ret = 0;
        int num = m_pNum->sub(1);
        if( 0 == num )
        {
            release();
        }
        return ret;
    }

    int module::add_ref()
    {
        int ret = 0;
        m_pNum->add(1);
        return ret;
    }

    int module::init()
    {
        int ret = 0;
        {
            m_pNum = mgr::container()->box()->lnum();
            m_pNum->set( 1 );
        }
        return ret;
    }

    int module::term()
    {
        int ret = 0;
        xos_stl::release_interface( m_pNum );
        close_servlet();
        delete_module_file();
        init_data();
        return ret;
    }

} // xos_http
